import json

import yaml
from datetime import datetime
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import Pt, Inches, RGBColor
from docx.oxml import OxmlElement
from docx.oxml.ns import qn


# 设置字体
def set_font(run, font_name='方正兰亭粗黑简体', font_size=12, bold=False):
    run.font.name = font_name
    run._element.rPr.rFonts.set(qn('w:eastAsia'), font_name)
    run.font.size = Pt(font_size)
    run.bold = bold


# 插入图片
def add_image_to_paragraph(paragraph, image_path, width=None):
    run = paragraph.add_run()
    run.add_picture(image_path, width=width)


# 设置页眉和页脚
def set_header_footer(doc, header_image, footer_image):
    section = doc.sections[0]

    # 设置页眉
    header = section.header
    header_paragraph = header.paragraphs[0]
    header_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    add_image_to_paragraph(header_paragraph, header_image, width=Inches(6.0))

    # 设置页脚
    footer = section.footer
    footer_paragraph = footer.paragraphs[0]
    footer_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    add_image_to_paragraph(footer_paragraph, footer_image, width=Inches(6.0))

    # 添加页码
    page_num_run = footer_paragraph.add_run(" - 第 ")
    set_font(page_num_run, font_size=10)
    page_num_field = OxmlElement('w:fldSimple')
    page_num_field.set(qn('w:instr'), 'PAGE')
    field_run = OxmlElement('w:r')
    field_text = OxmlElement('w:t')
    field_text.text = 'PAGE'
    field_run.append(field_text)
    page_num_field.append(field_run)
    footer_paragraph._element.append(page_num_field)
    total_page_run = footer_paragraph.add_run(" 页 -")
    set_font(total_page_run, font_size=10)


# 添加封面页
def add_cover_page(doc, version="V1.0"):
    doc.add_paragraph()
    doc.add_paragraph()
    doc.add_paragraph()
    doc.add_paragraph()
    doc.add_paragraph()
    doc.add_paragraph()
    doc.add_paragraph()
    # 产品标题
    product_page = doc.add_paragraph()
    product_page.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    run = product_page.add_run('产品名')
    set_font(run, font_size=20, bold=True)
    run.font.color.rgb = RGBColor(7, 32, 121)

    # 添加文档版本
    prdc_version_paragraph = doc.add_paragraph()
    prdc_version_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    version_run = prdc_version_paragraph.add_run("版本号")
    set_font(version_run, font_size=12)
    version_run.font.color.rgb = RGBColor(7, 32, 121)

    # 添加封面标题
    cover_page = doc.add_paragraph()
    cover_page.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    run = cover_page.add_run('API 手册')
    set_font(run, font_size=20, bold=True)
    run.font.color.rgb = RGBColor(7, 32, 121)

    # 添加文档版本
    version_paragraph = doc.add_paragraph()
    version_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    version_run = version_paragraph.add_run(f"文档版本: {version}")
    set_font(version_run, font_size=12)
    version_run.font.color.rgb = RGBColor(7, 32, 121)

    # 添加发布日期
    cover_subtitle = doc.add_paragraph()
    cover_subtitle.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    curDate = datetime.now().strftime('%Y-%m-%d')
    date_run = cover_subtitle.add_run(f"发布日期: {curDate}")
    set_font(date_run, font_size=12)
    date_run.font.color.rgb = RGBColor(7, 32, 121)  # 设置字体颜色

    # 添加分页符
    doc.add_page_break()

def add_notice_page(doc):
    notice_paragraph = doc.add_paragraph()
    notice_text = (
        "本文中出现的任何文字描述、文字格式、插图、照片、方法等内容，除另有特别注明，版权均属杭州安"
        "恒信息技术股份有限公司（简称“安恒信息”）所有，受到有关产权及版权法保护。任何个人、机构未"
        "经安恒信息的书面授权许可，不得以任何方式复制或引用本文的任何片段。\n"
        "经授权使用本文中内容的单位或个人，应在授权范围内使用，并注明“来源：安恒信息”。违反上述声"
        "明者，安恒信息保留追究其法律责任的权利。\n"
        "除杭州安恒信息技术股份有限公司的商标外，本手册中出现的其他商标、产品标识及商品名称，由各自"
        "权利人拥有"
    )
    notice_run = notice_paragraph.add_run(notice_text)
    set_font(notice_run, "宋体", font_size=11)

    doc.add_page_break()

# 添加目录页
def add_catalogue_page(doc):
    doc_title = doc.add_paragraph()
    doc_title.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    title_run = doc_title.add_run("目录")
    set_font(title_run, font_size=12, bold=True)
    title_run.font.color.rgb = RGBColor(88, 116, 181)
    doc.add_paragraph('')
    doc.add_page_break()

# 添加项目说明
def add_project_info(doc):
    # 添加文档说明标题
    doc_title = doc.add_paragraph()
    doc_title.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    title_run = doc_title.add_run("文档说明")
    set_font(title_run, font_size=16, bold=True)
    title_run.font.color.rgb = RGBColor(88, 116, 181)
    table = doc.add_table(rows=4, cols=2)
    table.style = 'Table Grid'

    doc.add_paragraph()

    # 添加修订记录标题
    modify_title = doc.add_paragraph()
    modify_title.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
    modify_run = modify_title.add_run("修订记录")
    set_font(modify_run, font_size=16, bold=True)
    modify_run.font.color.rgb = RGBColor(88, 116, 181)
    table = doc.add_table(rows=4, cols=4)
    table.style = 'Table Grid'

    # 添加分页符
    doc.add_page_break()


# 处理表格的创建与填充
def create_table(doc, headers, rows):
    table = doc.add_table(rows=1, cols=len(headers))
    table.style = 'Table Grid'
    hdr_cells = table.rows[0].cells
    for i, header in enumerate(headers):
        hdr_cells[i].text = header
        set_font(hdr_cells[i].paragraphs[0].runs[0], font_size=12, bold=True)

    for row in rows:
        row_cells = table.add_row().cells
        for i, cell_value in enumerate(row):
            row_cells[i].text = str(cell_value)
            set_font(row_cells[i].paragraphs[0].runs[0], font_size=12)
    return table


# 添加 API 详细信息
def add_api_details(doc, data, input_tag):
    api_title = doc.add_paragraph("API 详细信息")
    api_title.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    set_font(api_title.runs[0], font_size=20, bold=True)

    for path, methods in data['paths'].items():
        for method, details in methods.items():
            tags = details.get("tags", [])

            # 根据输入的 tag 进行过滤；若未指定 tag，则不过滤
            if input_tag and input_tag not in tags:
                continue

            # 添加 Summary 作为一级标题
            summary = details.get("summary", "")
            doc.add_paragraph(summary, style='Heading 1')
            set_font(doc.paragraphs[-1].runs[0], font_size=16, bold=True)

            doc.add_paragraph("请求参数", style='Heading 2')
            set_font(doc.paragraphs[-1].runs[0], font_size=12)
            # 添加 Path 和 Method
            doc.add_paragraph(f"Url: {path}")
            set_font(doc.paragraphs[-1].runs[0], font_size=14)

            doc.add_paragraph(f"  方法: {method.upper()}")
            set_font(doc.paragraphs[-1].runs[0], font_size=12)

            # 参数
            parameters = details.get("parameters", [])
            if parameters:
                params_title = doc.add_paragraph("  参数:")
                set_font(params_title.runs[0], font_size=12)

                param_rows = [
                    (param['name'], param['in'], str(param['required']), param.get('type', 'No type'), param.get('format', ''))
                    for param in parameters]
                create_table(doc, ['Name', 'In', 'Required', 'Type', 'Format'], param_rows)

            # 响应体
            responses = details.get("responses", {})
            if responses:
                doc.add_paragraph("返回内容:", style='Heading 2')
                set_font(doc.paragraphs[-1].runs[0], font_size=12)

                response_rows = []
                for status_code, response in responses.items():
                    description = response.get('description', 'No description provided')
                    schema_ref = response['schema'].get('$ref', 'No schema provided')
                    schema = resolve_info(schema_ref, data)
                    response_rows.append((status_code, description, schema))

                create_table(doc, ['Status Code', 'Description', 'Schema'], response_rows)


def resolve_info(ref, data, definitions=None):
    if not definitions:
        definitions = data.get('definitions', {})

    # 如果引用是字符串（例如 "$ref": "#/definitions/v1CommandEvent"），则获取最后的部分
    refs = ref.split("/")
    schema_name = refs[-1]

    # 查找对应的 schema 定义
    schema_def = definitions.get(schema_name)

    if not schema_def:
        return {}

    result = {}

    # 如果该定义包含嵌套引用，递归处理
    if schema_def.get('type') == 'object' and 'properties' in schema_def:
        for prop, prop_value in schema_def['properties'].items():
            # 如果该属性有 $ref，则递归解析
            if isinstance(prop_value, dict) and "$ref" in prop_value:
                ref = prop_value["$ref"]
                nested_schema = resolve_info(ref, data, definitions)
                result[prop] = nested_schema
            else:
                # 如果没有 $ref，直接获取类型
                result[prop] = prop_value.get("type", "No type")

    # 递归解析 array 类型的 items
    if schema_def.get('type') == 'array' and 'items' in schema_def:
        items_ref = schema_def['items'].get("$ref")
        if items_ref:
            result['items'] = resolve_info(items_ref, data, definitions)
        else:
            result['items'] = schema_def['items'].get("type", "No type")

    return result


def extract_properties(data):
    # 提取 schema 名称
    schema_ref = "#/definitions/v1ListCommandEventsResponse"
    schema = resolve_info(schema_ref, data)

    # 返回 JSON 字符串格式
    return json.dumps(schema, indent=2)

# 主程序
def main():
    input_tag = input("请输入希望导出 API 所属的标签 (按 Enter 返回所有 API): ").strip()
    print("loading...")

    # 加载 OpenAPI 文件
    with open('api.swagger.json', 'r', encoding='utf-8') as file:
        data = json.load(file)

    # 创建 Word 文档
    doc = Document()
    header_image_path = './header.png'  # 请替换为你的页眉图片路径
    footer_image_path = './footer.png'  # 请替换为你的页脚图片路径
    set_header_footer(doc, header_image_path, footer_image_path)

    # 添加封面页
    add_cover_page(doc)

    # 添加声明页
    add_notice_page(doc)

    # 添加项目说明
    add_project_info(doc)

    # 添加目录页
    add_catalogue_page(doc)

    # 添加 API 详细信息
    add_api_details(doc, data, input_tag)

    # 保存文档
    output_file = "API_Documentation_Filtered.docx" if input_tag else "API_Documentation_All.docx"
    doc.save(output_file)
    print(f"Word 文档生成成功：{output_file}，包含标签: {input_tag if input_tag else '所有标签'}")


if __name__ == "__main__":
    main()
